//--------------------------------------------------------------------------------
// This file is part of the Windows Workflow Foundation Sample Code
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is intended only as a supplement to Microsoft
// Development Tools and/or on-line documentation.  See these other
// materials for detailed information regarding Microsoft code samples.
// 
// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//--------------------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Workflow.ComponentModel;

namespace Microsoft.Samples.Workflow.UI.Design
{
    class TransitionCollectionEditor : CollectionEditor
    {
        Activity activity;

        public TransitionCollectionEditor()
            : base(typeof(TransitionCollection))
        {
        }

        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            object newValue = value;
            if (provider != null)
            {
                this.activity = context.Instance as Activity;
                if (this.activity == null)
                {
                    throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(Activity).FullName), "context.Instance");
                }

                IDesignerHost host = provider.GetService(typeof(IDesignerHost)) as IDesignerHost;
                if (host == null)
                {
                    throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));
                }

                TransitionCollection transitions = value as TransitionCollection;
                if (transitions == null)
                {
                    throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(TransitionCollection).FullName), "value");
                }

                ServiceContainer serviceContainer = provider.GetService(typeof(ServiceContainer)) as ServiceContainer;
                IReferenceService originalReferenceService = serviceContainer.GetService(typeof(IReferenceService)) as IReferenceService;
                if (originalReferenceService == null)
                {
                    throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IReferenceService).FullName));
                }

                serviceContainer.RemoveService(typeof(IReferenceService));
                serviceContainer.AddService(typeof(IReferenceService), new TransitionsReferenceService(originalReferenceService, provider));

                try
                {
                    foreach (Transition transition in transitions)
                    {
                        transition.Activity = activity;
                    }

                    newValue = new TransitionCollection();
                    foreach (Transition transition in transitions)
                    {
                        ((TransitionCollection)newValue).Add(transition);
                    }

                    base.EditValue(context, provider, newValue);

                    // If the collection is not changed, we return the original collection.
                    if (CompareCollection(transitions, newValue as TransitionCollection))
                    {
                        newValue = value;
                    }
                }
                finally
                {
                    serviceContainer.RemoveService(typeof(IReferenceService));
                    serviceContainer.AddService(typeof(IReferenceService), originalReferenceService);
                }
            }

            return newValue;
        }

        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.Modal;
        }

        protected override object CreateInstance(Type itemType)
        {
            object newObj = null;
            if (itemType == typeof(Transition))
            {
                IDesignerHost host = this.Context.GetService(typeof(IDesignerHost)) as IDesignerHost;
                if (host == null)
                    throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));

                Transition transition = new Transition();
                transition.Activity = this.activity;
                host.Container.Add(transition);
                newObj = transition;
            }
            else
            {
                newObj = base.CreateInstance(itemType);
            }

            return newObj;
        }

        protected override void DestroyInstance(object instance)
        {
            if (instance is Transition)
            {
                IDesignerHost host = this.Context.GetService(typeof(IDesignerHost)) as IDesignerHost;
                if (host == null)
                {
                    throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));
                }

                host.Container.Remove((Transition)instance);
            }

            base.DestroyInstance(instance);
        }

        bool CompareCollection(TransitionCollection original, TransitionCollection current)
        {
            if (original.Count != current.Count)
            {
                return false;
            }

            for (int i = 0; i < original.Count; i++)
            {
                if (original[i].Target != current[i].Target)
                {
                    return false;
                }
            }

            return true;
        }
    }
}